package com.lzy.okgo.harmony.rxharmony.plugins;

import io.reactivex.Scheduler;
import io.reactivex.exceptions.Exceptions;
import io.reactivex.functions.Function;

import java.util.concurrent.Callable;

/**
 * 工具类，提供一系列的static方法，外部可以调用进行配置，在特定时机，进行hook和处理
 */
public final class RxHarmonyPlugins {
    private static volatile Function<Callable<Scheduler>, Scheduler> onInitMainThreadHandler;
    private static volatile Function<Scheduler, Scheduler> onMainThreadHandler;

    /**
     * 工具类，隐藏构造方法，如果被反射，抛出异常
     */
    private RxHarmonyPlugins() {
        throw new AssertionError("No instances.");
    }

    /**
     * 初始化主线程调度器
     *
     * @param scheduler 默认的调度器，被Callable回调包裹
     * @return 要被应用的主线程调度器
     */
    public static Scheduler initMainThreadScheduler(Callable<Scheduler> scheduler) {
        //判空
        if (scheduler == null) {
            throw new NullPointerException("scheduler == null");
        }
        //如果有通过setInitMainThreadSchedulerHandler()方法设置了，hook回调函数，则通过hook回调函数进行处理，再返回调度器
        Function<Callable<Scheduler>, Scheduler> f = onInitMainThreadHandler;
        if (f == null) {
            //没有设置，判空后，再返回
            return callRequireNonNull(scheduler);
        }
        //设置了，调用设置的回调函数，进行处理
        return applyRequireNonNull(f, scheduler);
    }

    /**
     * 设置主线程调度器hook回调函数
     */
    public static void setMainThreadSchedulerHandler(Function<Scheduler, Scheduler> handler) {
        onMainThreadHandler = handler;
    }

    /**
     * 处理传入的Scheduler调度器
     */
    public static Scheduler onMainThreadScheduler(Scheduler scheduler) {
        if (scheduler == null) {
            throw new NullPointerException("scheduler == null");
        }
        Function<Scheduler, Scheduler> f = onMainThreadHandler;
        if (f == null) {
            return scheduler;
        }
        return apply(f, scheduler);
    }

    /**
     * 获取hook回调函数，可能为null
     */
    public static Function<Callable<Scheduler>, Scheduler> getInitMainThreadSchedulerHandler() {
        return onInitMainThreadHandler;
    }

    /**
     * 设置hook回调函数，可以对设置的调度器进行处理，再返回
     */
    public static void setInitMainThreadSchedulerHandler(Function<Callable<Scheduler>, Scheduler> handler) {
        onInitMainThreadHandler = handler;
    }

    /**
     * 返回配置hook回调函数
     *
     * @return 返回hook回调函数，可能为null
     */
    public static Function<Scheduler, Scheduler> getOnMainThreadSchedulerHandler() {
        return onMainThreadHandler;
    }

    /**
     * 重置所有配置
     */
    public static void reset() {
        setInitMainThreadSchedulerHandler(null);
        setMainThreadSchedulerHandler(null);
    }

    /**
     * 判空获取的Scheduler调度器，非null，则返回，为null则抛异常
     */
    static Scheduler callRequireNonNull(Callable<Scheduler> s) {
        try {
            Scheduler scheduler = s.call();
            if (scheduler == null) {
                throw new NullPointerException("Scheduler Callable returned null");
            }
            return scheduler;
        } catch (Throwable ex) {
            throw Exceptions.propagate(ex);
        }
    }

    /**
     * 调用传入的Function回调函数，对Scheduler进行处理
     *
     * @param f 回调函数
     * @param s Scheduler调度器
     * @return 要应用的调度器
     */
    static Scheduler applyRequireNonNull(Function<Callable<Scheduler>, Scheduler> f, Callable<Scheduler> s) {
        Scheduler scheduler = apply(f, s);
        if (scheduler == null) {
            throw new NullPointerException("Scheduler Callable returned null");
        }
        return scheduler;
    }

    /**
     * 调用回调函数对目标对象进行处理
     */
    static <T, R> R apply(Function<T, R> f, T t) {
        try {
            return f.apply(t);
        } catch (Throwable ex) {
            throw Exceptions.propagate(ex);
        }
    }
}